﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using PinCity.Models.Repositories;
using PinCity.Localization;
using PinCity.Models.ViewModels;
using PinCity.Models.Accounts;

namespace PinCity.Controllers
{
    public class AccountController : BaseController
    {
        log4net.ILog logger = log4net.LogManager.GetLogger(typeof(AccountController));
        RolesRepository _roles = new RolesRepository();
        UsersRepository _users = new UsersRepository();

        public ActionResult Index()
        {
            return this.Redirect("/");
        }

        /// <summary>
        /// Displays profile page for user.
        /// </summary>
        /// <param name="id">User's ID.</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Details(uint? id)
        {
            ActionResult result = null;
            if (id == null)
            {
                User current = this._users.GetUserByName(this.User.Identity.Name);
                if (current != null)
                {
                    result = this.View(current);
                }
                else
                {
                    result = this.Redirect("/");
                }
            }
            else
            {
                if (this._users.Contains((uint)id))
                {
                    result = this.View(this._users.Get((uint)id));
                }
                else
                {
                    result = this.Error404(LocalizationManager.GetString("userNotFoundMessage"));
                }
            }
            return result;
        }

        /// <summary>
        /// Displays a login form.
        /// </summary>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Login()
        {
            ActionResult result = null;
            if (this.User.Identity.IsAuthenticated)
            {
                result = this.Redirect("/");
            }
            else
            {
                result = this.View();
            }
            return result;
        }

        /// <summary>
        /// Retrieves login info and tries to log in a user.
        /// </summary>
        /// <param name="loginInfo">Info about user.</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Login(LoginViewModel loginInfo)
        {
            ActionResult result = null;
            if (Membership.ValidateUser(loginInfo.Login, loginInfo.Password))
            {
                FormsAuthentication.SetAuthCookie(loginInfo.Login, false);
                result = this.Redirect("/");
            }
            else
            {
                loginInfo.ErrorMessage = LocalizationManager.GetString("incorrectLoginOrPassword");
                result = this.View("Login", loginInfo);
            }
            return result;
        }

        /// <summary>
        /// Tries to log out current user and redirects him to home page.
        /// </summary>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Logout()
        {
            ActionResult result = null;
            if (User.Identity.IsAuthenticated)
            {
                FormsAuthentication.SignOut();
            }
            
            result = this.Redirect("/");
            return result;
        }

        /// <summary>
        /// Displays a form for registration info.
        /// </summary>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Register()
        {
            return this.View();
        }

        /// <summary>
        /// Receives info about new user and tries to register this user.
        /// On success authenticates user and redirects to home page.
        /// On failure redisplays a registration form.
        /// </summary>
        /// <param name="registerInfo"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Register(RegisterViewModel registerInfo)
        {
            ActionResult result = null;
            if (this._users.GetUserByName(registerInfo.Login) == null)
            {
                this._users.SaveOrUpdate(
                    new Models.Accounts.User(registerInfo.Login,
                                            registerInfo.Password,
                                            registerInfo.Email,
                                            DateTime.Now,
                                            DateTime.Now,
                                            DateTime.Now)
                                        );
                FormsAuthentication.SetAuthCookie(registerInfo.Login, false);
                result = this.Redirect("/");
            }
            else
            {
                registerInfo.ErrorMessage = LocalizationManager.GetString("duplicateLoginMessage");
                result = this.View(registerInfo);
            }
            return result;
        }

        /// <summary>
        /// Shows confirmation form for user deletion.
        /// </summary>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Delete()
        {
            return this.View();
        }

        /// <summary>
        /// Receives info about deleting user, tries to delete user from repo.
        /// On success removes user from repo, signs him out and redirects to home page.
        /// </summary>
        /// <param name="deleteInfo"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Delete(UserDeleteViewModel deleteInfo)
        {
            ActionResult result = null;
            User userToDelete = this._users.GetUserByName(deleteInfo.Login);
            if (userToDelete != null)
            {
                this._users.Delete(userToDelete);
                FormsAuthentication.SignOut();
                result = this.Redirect("/");
            }
            return result;
        }

        /// <summary>
        /// Displays a form for user edition.
        /// </summary>
        /// <param name="id">ID of user to edit.</param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Get)]
        public ActionResult Edit(uint id)
        {
            ActionResult result = null;
            User userToEdit = this._users.Get(id);

            if (userToEdit != null)
            {
                if (userToEdit.Login.Equals(this.User.Identity.Name))
                {
                    UserEditViewModel userToEditVM = new UserEditViewModel(userToEdit);
                    result = this.View(userToEditVM);
                }
                else
                {
                    result = this.Error403("editOwnAccountMessage");
                }
            }
            else
            {
                result = this.Error404(LocalizationManager.GetString("userNotFoundMessage"));
            }
            return result;
        }

        /// <summary>
        /// Receives info about user account changes.
        /// On success redirects to details page.
        /// </summary>
        /// <param name="editInfo"></param>
        /// <returns></returns>
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(UserEditViewModel editInfo)
        {
            ActionResult result = null;
            User userToUpdate = this._users.GetUserByName(editInfo.Login);
            if (userToUpdate != null)
            {
                if (editInfo.Login.Equals(this.User.Identity.Name))
                {
                    userToUpdate.Email = editInfo.Email;
                    userToUpdate.Password = editInfo.Password;
                    this._users.SaveOrUpdate(userToUpdate);
                    result = this.RedirectToAction("Details", new { id = userToUpdate.ID });
                }
                else
                {
                    result = this.Error403("editOwnAccountMessage");
                }
            }
            return result;
        }

    }
}
